﻿using LowCoding.Common;
using LowCoding.Common.JWT;
using LowCoding.Common.Security;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Text.RegularExpressions;

namespace LowCoding.API
{
    /// <summary>
    /// 请求token校验
    /// </summary>
    public class AuthorizationFilterAttribute : IAuthorizationFilter
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            if (!SkipAllowAnonymous(context))
            {
                //请求头中带有 Authorization 参数，并且参数值是token
                string token = context.HttpContext.Request.Headers["Authorization"];
                if (string.IsNullOrWhiteSpace(token))
                {
                    context.Result = new JsonResult(ToJsonTran.Fail(ResponseCodeEnum.Unauthozied, "Token has invalid signature"));
                    return;
                }
                else
                {
                    Regex r = new Regex("Bearer ");
                    token = r.Replace(token, "", 1);
                    LoginUserDto userDto = JwtTokenHelper.GetUserDto<LoginUserDto>(token);
                    if (userDto == null)
                    {
                        context.Result = new JsonResult(ToJsonTran.Fail(ResponseCodeEnum.Unauthozied, "Token has invalid signature"));
                        return;
                    }
                    else
                    {
                        if (userDto.ExpiryDateTime.AddMinutes(30) < DateTime.Now)
                        {
                            //token已超时且超过缓冲期，重新登录
                            context.Result = new JsonResult(ToJsonTran.Fail(ResponseCodeEnum.Token_Lose_Effect, "Token timeout"));
                            return;
                        }
                        else if (userDto.ExpiryDateTime < DateTime.Now)
                        {
                            //token已超时且未超过缓冲期，响应头返回新token
                            context.HttpContext.Response.Headers["access_token"] = AppManager.GetJwtString(userDto, DateTime.Now.AddHours(2));
                            context.HttpContext.Response.Headers["Access-Control-Expose-Headers"] = "access_token";
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 判断是否存在 AllowAnonymousAttribute
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        private static bool SkipAllowAnonymous(AuthorizationFilterContext context)
        {
            var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
            return controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true).Any(a => a.GetType().Equals(typeof(AllowAnonymousAttribute)))
                 || controllerActionDescriptor.ControllerTypeInfo.GetCustomAttributes(inherit: true).Any(a => a.GetType().Equals(typeof(AllowAnonymousAttribute)));
        }
    }
}